<template>
  <div ref="mapRef" class="map"></div>
</template>
<script setup>
import {
  defineProps,
  defineExpose,
  onMounted,
  ref,
  watch,
  nextTick
} from 'vue';
import { useRouter } from 'vue-router';
import GreatMap from '@/assets/greatmap/gmap-esm.js';
import LocationUtil from '@/utils/LocationUtil.js';
import VehicleAccessManager from '@/utils/VehicleAccessManager.js';
GreatMap.use(Cesium);
let geoSourceList = [];
let mvtProvider;
const router = useRouter();
// 组件属性
const props = defineProps({
  center: {
    type: Object,
    default: () => {}
  },
  geometry: {
    type: Array,
    default: () => []
  },
  startTime: {
    type: Number,
    required: true
  },
  endTime: {
    type: Number,
    required: true
  },
  areaId:{
    type: Number,
    required: true
  }
});
const mapRef = ref(null);
const HEIGHT_LEVEL_14 = 13000; //矢量数据显隐控制高度  低于它显示 高于它隐藏
let map; //地图容器
let mvtLayers = []; // 矢量图层
let vam; //车辆接入管理
let preHeight; //用于记录camera高度
// 加载底图
const loadMap = () => {
  map = new Cesium.Viewer(mapRef.value, {
    useDefaultRenderLoop: true, // 是否自动渲染
    geocoder: false, // 地理位置查询定位控件
    homeButton: false, // 默认相机位置控件
    timeline: false, // 时间滚动条控件
    navigationHelpButton: false, // 默认的相机控制提示控件
    fullscreenButton: false, // 全屏控件
    baseLayerPicker: false, // 底图切换控件
    animation: false, // 控制场景动画的播放速度控件
    selectionIndicator: false, // 取消双击追踪实体行为
    requestRenderMode: false, // 如果为 true，则仅在场景中的变化所确定的需要时才会渲染帧。
    // maximumRenderTimeChange: Infinity, // 如果requestRenderMode为true，这个值定义了在请求渲染之前允许的模拟时间的最大变化。
    sceneModePicker: false, // 不创建SceneModePicker小部件。
    infoBox: false, // 不创建 InfoBox 小部件。
    navigationInstructionsInitiallyVisible: false, // 如果导航说明最初应该是可见的，则为真，如果在用户明确单击按钮之前不应显示，则为假。
    imageryProvider: new Cesium.UrlTemplateImageryProvider({
      url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png ',
      subdomains: ['a', 'b', 'c', 'd']
    }), // 初始化默认球皮
    shouldAnimate: false, // 用于开启时钟视图模型
    sceneMode: Cesium.SceneMode.COLUMBUS_VIEW,
    showRenderLoopErrors: false, // 是否显示错误弹框
    orderIndependentTranslucency: true // 如果为 true 且配置支持，则使用与顺序无关的半透明。
  });
  map.imageryLayers.get(0).brightness = 2.5;
  // 开启抗锯齿
  map.scene.postProcessStages.fxaa.enabled = true;
  // js版本存在判断是否支持图像渲染像素化处理，目前不存在。后续可让用于自定义传入
  if (Cesium.defined(window.devicePixelRatio)) {
    // 设置屏幕分辨率尺度，解决渲染锯齿严重问题
    map.resolutionScale = window.devicePixelRatio;
  }
  // 移除双击追踪事件
  map.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
  /**
   *  在测试是否与地形发生碰撞之前，摄像机必须达到的最小高度。 此参数在旋转角度时，
   *  若当前高度大于此高度会根据数据移动点y轴计算渲染
   */
  map.scene.screenSpaceCameraController.minimumCollisionTerrainHeight = 1;
  // 修改操作模式左键平移、中键缩放、右键旋转
  map.scene.screenSpaceCameraController.zoomEventTypes = [
    Cesium.CameraEventType.WHEEL,
    Cesium.CameraEventType.PINCH
  ];
  map.scene.screenSpaceCameraController.tiltEventTypes = [
    Cesium.CameraEventType.PINCH,
    Cesium.CameraEventType.RIGHT_DRAG
  ];
  // 隐藏Cesium icon显示
  map.cesiumWidget.creditContainer.setAttribute('style', 'display:none');
  // 无论是否开启动画,隐藏Cesium动画控件
  const animationElements = document.getElementsByClassName(
    'cesium-viewer-animationContainer'
  );
  if (Cesium.defined(animationElements) && animationElements.length > 0) {
    animationElements[0].setAttribute('style', 'display:none');
  }
  // 无论是否开启时间轴,隐藏Cesium时间轴控件
  const timelineElements = document.getElementsByClassName(
    'cesium-viewer-timelineContainer'
  );
  if (Cesium.defined(timelineElements) && timelineElements.length > 0) {
    timelineElements[0].setAttribute('style', 'display:none');
  }
  map.scene.screenSpaceCameraController.maximumZoomDistance = 6045564;
  const {startTime, endTime} = props;
  vam = new VehicleAccessManager({
    startTime,
    endTime,
    areaId: 1,
    map
  });

  map.camera.moveEnd.addEventListener(()=>{
    const height = map.camera.positionCartographic.height;
    if(!preHeight) preHeight = height;
    if((height - HEIGHT_LEVEL_14)*(preHeight - HEIGHT_LEVEL_14) < 0){
      setVectorDataVisible(height - HEIGHT_LEVEL_14 < 0)
    }
    preHeight = height;
  })
  window.map = map;
};

let isVectorDatavisible = true; // 是否显示矢量数据 地图级别小于14级时不显示矢量数据

/** 获取视点字符串 */
const getViewPointStr = () =>{
  let result;
  if(map) {
    const camera = map.camera;
    const {positionCartographic , pitch, roll, heading} = camera;
    const {longitude, latitude, height} = positionCartographic;
    const viewpoint = {
      lng:Cesium.Math.toDegrees(longitude), 
      lat:Cesium.Math.toDegrees(latitude), 
      height, 
      pitch: Cesium.Math.toDegrees(pitch), 
      roll: Cesium.Math.toDegrees(roll), 
      heading: Cesium.Math.toDegrees(heading)
    };
    result = JSON.stringify(viewpoint)
  }
  return result;
}
window.getViewPointStr = getViewPointStr;

/** 组件挂载后事件回调 */
onMounted(() => {
  loadMap();
});

/** 清除地图要素 */
const clearMapInfo = () => {
  if (map) {
    map.dataSources.removeAll();
    geoSourceList = [];
    for (let i = mvtLayers.length - 1; i >= 0; i--) {
      map.imageryLayers.remove(mvtLayers[i]);
    }
    mvtLayers = [];
  }
  mvtProvider = undefined;
  if(congestionCollection) congestionCollection.removeAll();
  if(vam) vam.removeAll();
};


/** 设置地图路口干线 */
const addWfsLayer = (areaId, wfsServices) => {
  const style = {
    fill: Cesium.Color.fromAlpha(Cesium.Color.WHITE, 1),
    stroke: Cesium.Color.fromCssColorString('#4E8CDC'),
    strokeWidth: 3
  };
  clearMapInfo();
  let loadedServiceCount = 0;
  wfsServices.forEach((item) => {
    Cesium.GeoJsonDataSource.load(item.url, style).then((dataSource) => {
      loadedServiceCount++;
      geoSourceList.push(dataSource);
      if (HEIGHT_LEVEL_14 < map.camera.positionCartographic.height) dataSource.show = false;
      map.dataSources.add(dataSource);
       const entities = dataSource.entities.values;
      for (let i = 0; i < entities.length; i++) {
        const entity = entities[i];
        entity.type = item.geometryType;
        entity.areaId = areaId;
      }
      if(loadedServiceCount === wfsServices.length && congestionCollection){
        map.scene.primitives.add(congestionCollection)
      }
    });
  });
  const handler = new Cesium.ScreenSpaceEventHandler(map.scene.canvas);
  handler.setInputAction((evt) => {
    const pick = map.scene.pick(evt.position);
    if (Cesium.defined(pick) && pick.id) {
      const entity = pick.id;
      if (entity.type === 'intersection') {
        router.push({
          path: '/Crossing',
          query: {
            id: entity.areaId,
            crossingId: entity.properties.fid
          }
        });
        handler.destroy();
      } else if (entity.type === 'link') {
        router.push({
          path: '/TrunkRoad',
          query: {
            id: entity.areaId,
            trunkRoadId: entity.properties.fid
          }
        });
        handler.destroy();
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};

/** 添加矢量地图 */
const addMvtLayer = (mvtServices) => {
  clearMapInfo();
  const greatMap = new GreatMap();
  for (let i = 0; i < mvtServices.length; i++) {
    const item = mvtServices[i];
    greatMap.addSource({
      id: i + 1,
      type: GreatMap.SourceType.MVT,
      url: item.url
    });
  }
  mvtProvider = greatMap.getImageryProvider();
  if (HEIGHT_LEVEL_14 >= map.camera.positionCartographic.height) {
    Object.keys(mvtProvider).forEach((item) => {
      map.imageryLayers.addImageryProvider(mvtProvider[item]);
      mvtLayers.push(mvtProvider[item]);
    });
  }
};
let congestionColorArr = ['#4fd27d', '#ffd045', '#e80e0e','#b40000','#880505']
let congestionCollection = undefined;
const updateTrunkCongestionInfo = (data) =>{
  if(!congestionCollection){
    congestionCollection = new Cesium.PolylineCollection();
  }else{
    congestionCollection.removeAll();
  }
  data.forEach(({congestionLevel, pointList}) =>{
    if(congestionLevel !== 0){
      let material = Cesium.Material.fromType('Color',{
        color: Cesium.Color.fromCssColorString(congestionColorArr[congestionLevel])
      })
      pointList = pointList.map(item => parseFloat(item));
      let positions = Cesium.Cartesian3.fromDegreesArrayHeights(pointList);
      congestionCollection.add({
        positions,
        width: 4,
        material
      })
    }
  })
}

/** 控制地图上要素的显隐 */
const setVectorDataVisible = (visible) => {
  debugger
  isVectorDatavisible = visible;
  geoSourceList.forEach(datasource => {
    datasource.show = visible;
  });
  if (mvtProvider) {
    if (visible) {
      Object.keys(mvtProvider).forEach((item) => {
        map.imageryLayers.addImageryProvider(mvtProvider[item]);
        mvtLayers.push(mvtProvider[item]);
      });
    } else {
      mvtLayers.forEach(layer => {
        map.imageryLayers.remove(layer);
      });
      mvtLayers = [];
    }
  }
};

/** 查询时间段变化时，更新车辆查询参数 */
const onQueryTimeChange = () => {
  nextTick(()=>{
    console.log("Map onQueryTimeChange")
    const {startTime, endTime} = props;
    if(vam) vam.sendQueryMessage(startTime, endTime);
  })
};

/** 属性地图范围监听 */
watch(
  () => props.geometry,
  (v, ov) => {
    if (map) {
      LocationUtil.flyToGeometry(map, props.geometry);
    }
  },
  { deep: true }
);
/**属性地图中心点监听 */
watch(
  () => props.center,
  (v, ov) => {
    if (map) {
      LocationUtil.flyToCenter(map, props.center);
    }
  },
  { deep: true }
);
/**对外暴漏接口 */
defineExpose({
  addWfsLayer,
  addMvtLayer,
  onQueryTimeChange,
  clearMapInfo,
  updateTrunkCongestionInfo
});
</script>
<style scoped>
.map {
  width: 100%;
  height: calc(100% - 3.625rem);
  position: absolute;
  left: 0;
  top: 3.625rem;
}
</style>
